package cn.jingyuan.swan.gw.locator;

import cn.jingyuan.swan.gw.service.RouteService;
import org.springframework.cloud.netflix.zuul.RoutesRefreshedEvent;
import org.springframework.cloud.netflix.zuul.filters.SimpleRouteLocator;
import org.springframework.cloud.netflix.zuul.filters.ZuulProperties;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.util.StringUtils;

import java.util.LinkedHashMap;
import java.util.Map;


public class RemoteRouteLocator extends SimpleRouteLocator {
    // https://blog.csdn.net/tianyaleixiaowu/article/details/77933295?locationNum=5&fps=1
    // https://www.jianshu.com/p/5e5197e00d65

    private final ApplicationEventPublisher eventPublisher;

    private final ZuulProperties zuulProperties;

    private final RouteService routeService;

    public RemoteRouteLocator(
        String servletPath,
        ZuulProperties zuulProperties,
        RouteService routeService,
        ApplicationEventPublisher eventPublisher) {
        super(servletPath, zuulProperties);
        this.zuulProperties = zuulProperties;
        this.routeService = routeService;
        this.eventPublisher = eventPublisher;
    }

    @Override
    public void doRefresh() {
        super.doRefresh();
        // 发布本地刷新事件，更新相关本地缓存，解决动态加载完，新路由映射无效的问题。
        eventPublisher.publishEvent(new RoutesRefreshedEvent(this));
    }

    @Override
    protected Map<String, ZuulProperties.ZuulRoute> locateRoutes() {
        LinkedHashMap<String, ZuulProperties.ZuulRoute> routesMap = new LinkedHashMap<>();
        // 加载 application.properties 路由信息
        routesMap.putAll(super.locateRoutes());
        // 加载远程路由信息
        routesMap.putAll(routeService.getRoutes());

        // 优化一下配置
        LinkedHashMap<String, ZuulProperties.ZuulRoute> zuulRoutes = new LinkedHashMap<>();
        for (Map.Entry<String, ZuulProperties.ZuulRoute> entry : routesMap.entrySet()) {
            String path = entry.getKey();
            if (!path.startsWith("/")) {
                path = "/" + path;
            }

            if (StringUtils.hasText(zuulProperties.getPrefix())) {
                path = zuulProperties.getPrefix() + path;
                if (!path.startsWith("/")) {
                    path = "/" + path;
                }
            }

            zuulRoutes.put(path, entry.getValue());
        }
        return zuulRoutes;
    }

}
